<!--
 * @Author: wangshuixin 2412658453@qq.com
 * @Date: 2024-06-01 01:02:46
 * @LastEditors: wangshuixin 2412658453@qq.com
 * @LastEditTime: 2024-11-05 09:06:25
 * @FilePath: /web-components-box/components/Tag/TypeTag.vue
 * @Description: 标签组件
-->
<script setup lang="tsx">
interface TypeTagObject {
  title?: string, // tag标题
  name?: string, // tag标题
  code?: string, // tag编码
  hash?: string, // 哈希值，用于区分相同的tag
  [property: string]: any
} 
const props = defineProps({
  placeHolder: {
    type: String,
    default: '请输入内容'
  },
  data: {
    type: Array<TypeTagObject|String>,
    required: true,
    default: ['测试标签',{title:'title标签'},{name:'name标签'}]
  },
  alwaysInput: { // 新增输入后，输入框重新展示出来
    type: Boolean,
    default: true
  },
  editable: { // 可编辑的
    type: Boolean,
    default: false
  }
})
const emits = defineEmits(['editSuccess'])
// 移除的Tag标签
const removedTag = ref<TypeTagObject>()
// 编辑的Tag标签
const editedTag = ref<TypeTagObject>()
// 被双击的Tag标签
const dblclickTag = ref<TypeTagObject>()
// 双击Tag 的标记
const dblclickFlag = ref(false)
// TypeTag显示的标签 数据源
const tagList = ref<TypeTagObject>(props.data.map((tag: TypeTagObject|String) => {
  if (typeof tag === 'string') {
    return {
      title: tag
    }
  } else if (typeof tag === 'object' && (!!(tag as TypeTagObject)?.title || !!(tag as TypeTagObject)?.name)) {
    return {
      ...tag,
      title: !!(tag as TypeTagObject)?.title ? (tag as TypeTagObject).title : (tag as TypeTagObject)?.name,
    }
  } else {
    throw new Error('tag必须是字符串或有title、name的对象（值为空，视为不存在）')
  }
}))

// 监听tagList里面的标签发生变动（初始化、移除事件 会监听到）
watch(
  () => tagList.value,
  () => {
    if (tagList.value.length > 0) {
      tagList.value.forEach((tag: TypeTagObject , index: number) => {
        const hash = computeWebHash(createUniqueString(index)) as string  
        tag.hash = hash
      })
    }
  },
  {
    immediate: true
  }
)

// 监听是否有 移除Tag 的事件
watch(
  () => removedTag.value,
  () => {
    tagList.value = tagList.value.filter((item: TypeTagObject) => item !== removedTag.value)
    emits('editSuccess', tagList.value)
  },
  {
    immediate: true
  }
)

// 显示新增input输入框
const showTypeTagInput = ref(false)
// 新增input输入框
const typeTagInputRef = ref()
// 新增input输入框的值
const typeTagInputValue = ref('')
// 监听“新增input输入框” 是否显示 的事件
watch(
  () => showTypeTagInput.value,
  () => {
    if (showTypeTagInput.value) {
      inputFocus(typeTagInputRef)
    } else if (typeTagInputValue.value !== undefined && typeTagInputValue.value.trim() !== '') {
      const hash = computeWebHash(createUniqueString(tagList.value.length)) as string
      tagList.value.push({title: typeTagInputValue.value.trim(), hash})
      emits('editSuccess', tagList.value)
      nextTick(() => {
        if (props.alwaysInput && !showTypeTagInput.value) {
          showTypeTagInput.value = true
        }
      })
    }
    typeTagInputValue.value = '' // 重置新增输入框的值
  },
  {
    immediate: true
  }
)
// 监听Tag标签被双击的事件
watch(
  () => dblclickTag.value,
  () => {
    const hash = dblclickTag.value?.hash
    nextTick(() => {
      if (!!hash) {
        const tagEditedInput = document.getElementById(hash)!.querySelector('input') as HTMLInputElement
        inputFocus(tagEditedInput)
      }
    })
  },
  {
    immediate: true
  }
)
</script>
<template>
  <div>
    <div v-if="props.editable" class="pods-type-tag relative flex flex-wrap margin-[0px] h-auto pb-[16px] pl-[16px] pr-[16px]">
      <div v-for="tag in tagList" :key="tag.hash">
        <a-input
          class="mr-[12px] mt-[12px]" v-if="dblclickTag === tag && dblclickFlag"
          :id="tag.hash" v-model="tag.title" :style="{width:'230px'}" :placeholder="props.placeHolder"
          :max-length="10" allow-clear show-word-limit
          @blur="dblclickFlag = false, dblclickTag = undefined, tagList = tagList.filter((item: TypeTagObject) => item.title !== '' && item.title !== undefined), emits('editSuccess', tagList)"
          @keydown.enter="dblclickFlag = false, dblclickTag = undefined"
        />
        <a-tag
          v-else class="tag-editable mr-[20px] mt-[12px] cursor-pointer"
          :closable="editedTag === tag"
          @close="() => removedTag = tag"
          @mouseover="() => editedTag = tag"
          @mouseleave="() => editedTag = undefined"
          @dblclick="() => { dblclickFlag = true, editedTag = undefined, dblclickTag = tag }"
        >
          {{ tag.title }}
        </a-tag>
      </div>
      <a-input
        class="mr-[12px] mt-[12px]" v-if="showTypeTagInput"
        ref="typeTagInputRef" v-model="typeTagInputValue" :style="{width:'230px'}" :placeholder="props.placeHolder"
        :max-length="10" allow-clear show-word-limit
        @blur="showTypeTagInput = false"
        @keydown.enter="showTypeTagInput = false"
      />
      <a-button class="mr-[4px] mt-[12px]" type="primary" @click.stop="showTypeTagInput = true">新&nbsp;&nbsp;增</a-button>
    </div>
    <div v-else>
      <div v-if="tagList.length > 0" class="pods-type-tag flex flex-wrap margin-[0px] h-auto pb-[16px] pl-[16px] pr-[16px]">
        <div v-for="tag in tagList" :key="tag.hash">
          <a-tag class="mr-[20px] mt-[12px]">
            {{ tag.title }}
          </a-tag>
        </div>
      </div>
      <a-empty v-else />
    </div>
  </div>
</template>
<style scoped lang="less">
.pods-type-tag {
  :deep(.arco-tag-size-medium) {
    height: 32px;
  }
  .tag {
    &-editable:hover {
      margin-right: 4px;
    }
  }
}
</style>